package router;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import packets.LSA;

import router.interf.Interface;
import statemachine.NeighborStateMachine;
import statemachine.State;
import statemachine.StateInterface;

import events.EventManager;
import events.RouterDeadEvent;
import events.RouterDeadEvent;



public class NeighborDataStructure {
	
	private InetAddress neighborID;
	private InetAddress BDR;
	private InetAddress DR;
	private StateInterface state;
	private Timer inactivityTimer;
	private boolean masterSlave;
	private int seqNumber;
	private int priority;
	private NeighborStateMachine stateMachine;
	private Interface attachedInterface;
	
	private ArrayList<LSA> LinkStateRequestList;
	private ArrayList<LSA> LinkStateRetransmissionList;
	private ArrayList<LSA> DatabaseSummaryList; 
	
	
	// Innere Klasse: Diese Taks wird dem inactivityTimer übergeben; hierdurch wird das Ereignis "Timer Expired" aufgerufen.
	private class InactivityTimerTask extends TimerTask
	{	
		private NeighborDataStructure neighbor;
		
		public InactivityTimerTask(NeighborDataStructure neighbor){
			this.neighbor = neighbor;		
		}
		
		public NeighborDataStructure getNeighbor(){
			return this.neighbor;
		}
		
		@Override
		public void run() {
					EventManager.getInstance().notifyTimerExpired(new RouterDeadEvent(neighbor));
			
		}
		
	}
	
	public ArrayList<LSA> getLinkStateRequestList(){
		return this.LinkStateRequestList;
	}
	
	public ArrayList<LSA> getLinkStateRetransmissionList(){
		return this.LinkStateRetransmissionList;
	}
	
	public ArrayList<LSA> getDatabaseSummaryList(){
		return this.DatabaseSummaryList;
	}
	
	
	public NeighborDataStructure(InetAddress id, int seqNumber, Interface attachedInterface){
		
		this.stateMachine = NeighborStateMachine.getInstance();
		this.neighborID = id;
		this.state = stateMachine.getStateByName("Down");
		this.attachedInterface = attachedInterface;
		
		// Timer erzeugen. Nach 30 Sekunden läuft dieser aus und ruft das entsprechende Event im EventManager auf.
		this.inactivityTimer = new Timer();
		inactivityTimer.schedule(new InactivityTimerTask(this), 30000);
		
		this.seqNumber = seqNumber;
	}
	
	public void changeState(String word){
		
		this.state = stateMachine.transit(this.state, word);
		
	}
	
	public InetAddress getBDR(){
		return this.BDR;
	}
	
	public InetAddress getDR(){
		return this.DR;
	}
	
	public InetAddress getNeighborID() {
		return neighborID;
	}
	
	public void setNeighborID(InetAddress neighborID) {
		this.neighborID = neighborID;
	}
	public StateInterface getState() {
		return state;
	}
	public void setState(State state) {
		this.state = state;
	}
	public Timer getInactivityTimer() {
		return inactivityTimer;
	}
	public void setInactivityTimer(Timer inactivityTimer) {
		this.inactivityTimer = inactivityTimer;
	}
	public boolean isMasterSlave() {
		return masterSlave;
	}
	public void setMasterSlave(boolean masterSlave) {
		this.masterSlave = masterSlave;
	}
	public int getSeqNumber() {
		return seqNumber;
	}
	public void setSeqNumber(int seqNumber) {
		this.seqNumber = seqNumber;
	}
	public int getPriority() {
		return priority;
	}
	public void setPriority(int priority) {
		this.priority = priority;
	}
	public Interface getAttachedInterface() {
		return attachedInterface;
	}
	public void setAttachedInterface(Interface attachedInterface) {
		this.attachedInterface = attachedInterface;
	}
	
	
	
	

}
